/*
 * Mask.java
 *
 * Created on August 19, 2004, 10:05 PM
 */

/**
 *
 * @author  pablo
 */
package edu.umd.essic.maskbuilder;

import java.awt.geom.*;
import java.awt.Point;
import java.awt.Rectangle;
import java.io.*;

public class Mask {
    
    private Node[][] matrix;
    private int size_x, size_y;
    private int flag = 1;
    private boolean multi_layer = false;
    private int edit_method = 1;
    
    /** Creates a new instance of Mask */
    public Mask(int SX, int SY) {
        matrix = new Node[SX][SY];
        size_x = SX;
        size_y = SY;
    }
    
    public int[][] GetMask(){
        int[][] msk = new int[size_x][size_y];
        for (int i=0;i<size_x;i++){
            for (int j=0;j<size_y;j++){
               msk[i][j] = matrix[i][j].flag;
            }
        }
        return msk;
    }
    
    public int GetLonDim(){
        return size_x;
    }
    
    public int GetLatDim(){
        return size_y;
    }
    
    public void SetFlag(int Flag){
        flag = Flag; 
    }
    
    public int GetFlag(){
        return flag;
    }
    
    public void SetMethod(int method){
        edit_method = method;
    }
    
    public void ResetFlag(){
        flag = 1;
    }
    
    public void SetMultiProperty(boolean prop){
        multi_layer = prop;
    }
    
    public boolean GetMultiProperty(){
        return multi_layer;
    }
    
    public void SetNode(int X, int Y, float xx, float yy, int flag){
        matrix[X][Y] = new Node(xx,yy,flag);
    }
    
    public Point GetNode(int i, int j, float zoom_level){
        Point result = new Point(Math.round(matrix[i][j].x*zoom_level),Math.round(matrix[i][j].y*zoom_level));
        return result;
    }

    public Point[][] GetNodes(float zoom_level){
        Point[][] result = new Point[size_x][size_y];
        for(int i=0;i<size_x;i++){
            for(int j=0;j<size_y;j++){
                result[i][j] = new Point(Math.round(matrix[i][j].x*zoom_level),Math.round(matrix[i][j].y*zoom_level));
            }
        }
        return result;
    }
    
    public int CheckNode(int X, int Y){
        return matrix[X][Y].flag;
    }
 
    public void ReadMask(BufferedReader r, int nx, int ny, Point2D.Float[][] coord, int mask_type) throws IOException{
        Pos p = new Pos();
        int largest = 0;
        int count_flags = 0;
        for (int j=0; j<ny; j++){
            String line = r.readLine();
            for (int i=0; i<nx; i++){
                int x,y;
                if (mask_type != 0){
                    x = Math.round((coord[i+1][j].x+coord[i][j].x)/2);
                    y = Math.round((coord[i][j+1].y+coord[i][j].y)/2);
                } else {
                    x = Math.round(coord[i][j].x);
                    y = Math.round(coord[i][j].y);
                }
                int num = p.ReadInt(line);
                if (largest < num) {
                    largest = num;
                    count_flags ++;
                }
                if (num != 0){
                    flag = num; 
                    SetNode(i,j,x,y,flag);
                }
                else{
                    flag = 0;                
                    SetNode(i,j,x,y,flag);
                }
            }
            p.SetZero();
        }
        flag = largest;
        if (count_flags > 1) multi_layer = true;
        p = null;
    }
 
    public void ChangeFlag(Point[] p, int edit_flag){
        for (int i=p[0].x; i<p[1].x; i++){
            for (int j=p[0].y; j<p[1].y; j++){
                EditMask(i,j,edit_flag);
            }
        }
    }  
    
    public int CorrectBoundaries(){
        int count = 0;        
        for(int i=0;i<size_x;i++){
            for(int j=0;j<size_y;j++){
                if (matrix[i][j].flag != 0){
                    if (Channel(i,j)){
                        matrix[i][j].flag = 0; 
                        count++;
                    }
                    if (BadBoundary(i,j)){
                        matrix[i][j].flag = 0; 
                        count++;
                    }
                }
            }
        }
        return count;
    }
    
    private boolean BadBoundary(int i, int j){
        boolean answer = false;
        int count=0;
        int flag1,flag2,flag3,flag4;
        if (i==0) flag1 = 0;        else flag1 = matrix[i-1][j].flag;
        if (i==size_x-1) flag2 = 0; else flag2 = matrix[i+1][j].flag;        
        if (j==0) flag3 = 0;        else flag3 = matrix[i][j-1].flag;
        if (j==size_y-1) flag4 = 0; else flag4 = matrix[i][j+1].flag;
        if (flag1 == 0) count++;
        if (flag2 == 0) count++;
        if (flag3 == 0) count++;
        if (flag4 == 0) count++;
        if (count>2) answer = true;        
        return answer;
    }
    private boolean Channel(int i, int j){
        boolean answer = false;
        int flag1,flag2,flag3,flag4;
        if (i==0) flag1 = 0;        else flag1 = matrix[i-1][j].flag;
        if (i==size_x-1) flag2 = 0; else flag2 = matrix[i+1][j].flag;        
        if (j==0) flag3 = 0;        else flag3 = matrix[i][j-1].flag;
        if (j==size_y-1) flag4 = 0; else flag4 = matrix[i][j+1].flag; 
        if (((flag1 == 0)&&(flag2 == 0)&&(flag3 != 0)&&(flag4 != 0)) ||
           ((flag1 != 0)&&(flag2 != 0) &&(flag3 == 0)&&(flag4 == 0)))
            answer = true;
        return answer;
    }
    
    public void ChangeFlag(Point p, int edit_flag){
        int i=p.x; int j = p.y;
        EditMask(i,j,edit_flag);
    }  
    
    private void EditMask(int i, int j, int edit_flag){
        switch (edit_method){
            case 1: 
                if (matrix[i][j].flag == 0) 
                    matrix[i][j].flag = edit_flag;
                else
                    matrix[i][j].flag = 0;
                break;
            case 2: matrix[i][j].flag = 0; break;
            case 3: matrix[i][j].flag = edit_flag; break;
        }                
    }
    
    
       
}
